package com.zn.bitmapDisplay
{
	import flash.display.Bitmap;
	import flash.display.FrameLabel;
	import flash.display.MovieClip;
	import flash.display.Sprite;
	import flash.display.Stage;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.events.TimerEvent;
	import flash.geom.Point;
	import flash.geom.Rectangle;
	import flash.utils.Timer;
	
	dynamic public class BitmapMovieClip extends MovieClip
	{
		public static const MOUSE_IN_EVENT:String = "mouseInEvent";
		
		public static const MOUSE_OUT_EVENT:String = "mouseOutEvent";
		
		public static const KEY_FRAME_EVENT:String="keyFrameEvent";
		
		public var bitmapDataVO:BitmapDataVO;
		
		public var bitmap:Bitmap = new Bitmap(null, "auto", true);
		
		public var sp:Sprite = new Sprite();
		
		private var _currentFrame:int = 1;
		
		private var _currentFrameLabel:String = "";
		
		private var _isPlay:Boolean = false;
		
		/**
		 *是否循环
		 */
		public var loop:Boolean = false;
		
		private var _frameRate:uint = 1;
		
		/**
		 *播放完一次后，是否发布完成消息
		 */
		public var isDispatchCompleteEvent:Boolean = false;
		
		private var _startFrame:int = 1;
		
		/**
		 *初始化完成后是否播放
		 */
		private var _doPlayFlag:Boolean;
		
		private var _isDestroy:Boolean = false;
		
		private var _buttonMode:Boolean;
		
		private var rootStage:Stage;
		
		private var _point:Point = new Point();
		
		private var _timer:Timer;
		
		public var keyFrameDic:Object={};
		
		public function BitmapMovieClip(bitmapDataVO:BitmapDataVO = null)
		{
			super();
			
			addEventListener(Event.ADDED_TO_STAGE, addToStageHandler);
			addEventListener(Event.REMOVED_FROM_STAGE, removeFromStageHandler);
			addEventListener(MouseEvent.ROLL_OUT, mouseRollOutHandler);
			
			addChild(sp);
			sp.mouseChildren = sp.mouseEnabled = false;
			
			sp.addChild(bitmap);
			
			_timer = new Timer(1000);
			_timer.addEventListener(TimerEvent.TIMER, timerHandler);
			
			init(bitmapDataVO);
		}
		
		protected function timerHandler(event:TimerEvent):void
		{
			nextFrame();
		}
		
		protected function removeFromStageHandler(event:Event):void
		{
			if (rootStage)
				rootStage.removeEventListener(MouseEvent.MOUSE_MOVE, mouseMoveHandler);
		}
		
		protected function addToStageHandler(event:Event):void
		{
			rootStage = stage;
			rootStage.addEventListener(MouseEvent.MOUSE_MOVE, mouseMoveHandler);
		}
		
		public function init(bitmapDataVO:BitmapDataVO):void
		{
			this.bitmapDataVO = bitmapDataVO;
			
			if (bitmapDataVO && !_isDestroy)
			{
				keyFrameDic=bitmapDataVO.keyFrameDic;
				BitmapDataManager.addBitmapDataVOCount(bitmapDataVO);
				gotoAndStop(1);
				if (_doPlayFlag)
					play();
			}
		}
		
		public override function get currentFrame():int
		{
			return _currentFrame;
		}
		
		public override function get currentFrameLabel():String
		{
			return _currentFrameLabel;
		}
		
		public override function get currentLabels():Array
		{
			return bitmapDataVO.currentLabels;
		}
		
		public override function gotoAndPlay(frame:Object, scene:String = null):void
		{
			gotoAndStop(frame);
			play();
		}
		
		public override function gotoAndStop(frame:Object, scene:String = null):void
		{
			stop();
			
			gotoFrame(frame);
		}
		
		private function gotoFrame(frame:Object):void
		{
			if (!bitmapDataVO)
				return;
			
			_currentFrame = getFrameIndex(frame);
			updateCurrentFrameLabel();
			
			bitmap.bitmapData = bitmapDataVO.bitmapDataList[_currentFrame - 1];
			
			var rect:Rectangle = bitmapDataVO.bitmapDataRectList[_currentFrame - 1];
			bitmap.x = rect.x;
			bitmap.y = rect.y;
			
			updateBitmapPoint();
			//				graphics.clear();
			//				graphics.beginFill(0x00FF00,0.5);
			//				graphics.drawRect(rect.x,rect.y,rect.width,rect.height);
			//				graphics.endFill();
			
			checkKeyFrame();
		}

		public function checkKeyFrame():void
		{
			if(keyFrameDic[_currentFrame])
				dispatchEvent(new Event(KEY_FRAME_EVENT));
		}

		
		public override function nextFrame():void
		{
			_currentFrame++;
			if (_currentFrame >= totalFrames)
			{
				_currentFrame = totalFrames;
				
				if (isDispatchCompleteEvent)
					dispatchEvent(new Event(Event.COMPLETE, true, true));
				
				if (!loop || totalFrames == 1)
					stop();
				else
				{
					gotoFrame(_currentFrame);
					
					_currentFrame = startFrame - 1;
					return;
				}
			}
			
			gotoFrame(_currentFrame);
		}
		
		public override function play():void
		{
			if (bitmapDataVO == null)
			{
				_doPlayFlag = true;
				return;
			}
			
			if (_isPlay)
				return;
			
			_isPlay = true;
			
			_timer.start();
		}
		
		public override function prevFrame():void
		{
			_currentFrame--;
			if (_currentFrame < 1)
			{
				_currentFrame = 1;
				if (!loop)
					stop();
			}
			
			gotoFrame(_currentFrame);
		}
		
		public override function stop():void
		{
			if (!_isPlay)
				return;
			
			_isPlay = false;
            _timer.stop();
		}
		
		public override function get totalFrames():int
		{
			if (bitmapDataVO && bitmapDataVO.bitmapDataList)
				return bitmapDataVO.bitmapDataList.length;
			return 1;
		}
		
		public function getFrameIndex(frame:Object):uint
		{
			if (frame is String)
			{
				if (bitmapDataVO.frameLabelDic[frame] != null)
				{
					return bitmapDataVO.frameLabelDic[frame];
				}
				else
				{
					trace("FrameLabel not found");
				}
			}
			else if (frame is uint)
			{
				var goToFrame:uint = uint(frame);
				if (frame > totalFrames || frame < 1)
				{
					goToFrame = 1;
				}
				return goToFrame;
			}
			return 1;
		}
		
		
		private function updateCurrentFrameLabel():void
		{
			if (!bitmapDataVO)
				return;
			
			var frameLabel:FrameLabel = bitmapDataVO.currentLabels[_currentFrame - 1];
			if (frameLabel)
			{
				_currentFrameLabel = frameLabel.name;
			}
		}
		
		public function destroy():void
		{
			stop();
			
			if (parent)
				parent.removeChild(this);
			
			if (rootStage)
				rootStage.removeEventListener(MouseEvent.MOUSE_MOVE, mouseMoveHandler);
			
			removeEventListener(Event.ADDED_TO_STAGE, addToStageHandler);
			removeEventListener(Event.REMOVED_FROM_STAGE, removeFromStageHandler);
			removeEventListener(MouseEvent.ROLL_OUT, mouseRollOutHandler);
			
			rootStage = null;
			bitmap = null;
			
			BitmapDataManager.removeBitmapDataVOCount(bitmapDataVO);
			bitmapDataVO = null;
			
			_currentFrameLabel = "";
			
			if(_timer)
				_timer.removeEventListener(TimerEvent.TIMER, timerHandler);
			_timer = null;
			
			keyFrameDic=null;
			_isDestroy = true;
		}
		
		/**
		 *开始播放的帧
		 */
		public function get startFrame():int
		{
			return _startFrame;
		}
		
		/**
		 * @private
		 */
		public function set startFrame(value:int):void
		{
			_startFrame = Math.min(value, totalFrames);
		}
		
		public function clone():BitmapMovieClip
		{
			var mc:BitmapMovieClip = new BitmapMovieClip(bitmapDataVO);
			mc.loop = loop;
			mc.frameRate = frameRate;
			mc.isDispatchCompleteEvent = isDispatchCompleteEvent;
			if (_isPlay)
				mc.play();
			
			return mc;
		}
		
		protected function mouseMoveHandler(event:MouseEvent):void
		{
			if (isMouseOver)
			{
				mouseChildren = mouseEnabled = true;
				
				if (buttonMode)
					super.buttonMode = true;
				
				dispatchEvent(new Event(MOUSE_IN_EVENT));
			}
			else
			{
				mouseChildren = mouseEnabled = false;
				super.buttonMode = false;
				dispatchEvent(new Event(MOUSE_OUT_EVENT));
			}
		}
		
		protected function mouseRollOutHandler(event:MouseEvent):void
		{
			dispatchEvent(new Event(MOUSE_OUT_EVENT));
		}
		
		public function get isMouseOver():Boolean
		{
			var b:Boolean = false;
			
			try
			{
				var x:Number = mouseX - bitmap.x - sp.x;
				var y:Number = mouseY - bitmap.y - sp.y;
				if (bitmap && bitmap.bitmapData && bitmap.bitmapData.getPixel32(x, y) != 0)
					b = true;
			}
			catch (error:Error)
			{
				
			}
			
			return b;
		}
		
		
		public override function get buttonMode():Boolean
		{
			return _buttonMode;
		}
		
		public override function set buttonMode(value:Boolean):void
		{
			_buttonMode = value;
		}
		
		public function get point():Point
		{
			return _point;
		}
		
		public function set point(value:Point):void
		{
			_point = value;
			updateBitmapPoint();
		}
		
		private function updateBitmapPoint():void
		{
			sp.x = -point.x;
			sp.y = -point.y;
		}
		
		/**
		 *帧率 ,一秒多少帧
		 */
		public function get frameRate():uint
		{
			return _frameRate;
		}
		
		/**
		 * @private
		 */
		public function set frameRate(value:uint):void
		{
			_frameRate = value;
			
			_timer.stop();
			_timer.delay = 1000 / frameRate;
			if (_isPlay)
                _timer.start();
		}
		
	}
}
